package foundation;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Observable;
import java.util.Observer;
import javax.imageio.ImageIO;

public class FVideoReader extends Observable implements Runnable
{

	private int RECONNECT_DELAY = 5000;
	private final int TIMEOUT = 5000;
	private boolean connected = false;
	private boolean firstError = true;
	private String requestUrl;
	private FStatusNotifier statusNotifier = new FStatusNotifier();
	private String[] okText = {"OK","Webcam connection ok."};
	private String[] errText = {"NC","No connection to webcam. Check error log."};
	
	public FVideoReader(String requestUrl) {
		this.requestUrl = requestUrl;
	}
	
	public String readLine(InputStream istream) throws Exception {
		String line = "";
		int readByte;
		while ((readByte = istream.read()) != 13) {
			if (readByte < 0) {
				throw (new IOException());
			}
    		line += (char) readByte;
    	}
    	istream.read();
		
    	return line;
	}
	
	public void addStatusObserver(Observer obs) {
		statusNotifier.addObserver(obs);
	}
	
	public void deleteStatusObserver(Observer obs) {
		statusNotifier.deleteObserver(obs);
	}
	
	@Override
	public void run() {
        BufferedImage image = null;
        int length;
        String line = "";
        byte[] byteArray;
        InputStream in;
        boolean start = false;
        InputStream istream = null;
        
        while (true)
        {
			try {
				URL url = new URL(requestUrl.toString());
				URLConnection conn = url.openConnection();
				// setting these timeouts ensures the client does not deadlock indefinitely
				// when the server has problems.
				conn.setConnectTimeout(TIMEOUT);
				conn.setReadTimeout(TIMEOUT);
				istream = conn.getInputStream();
				statusNotifier.setChanged();
				statusNotifier.notifyObservers(okText);
				connected = true;
				firstError = true;
				int count;
				int bytesRead;
				while (true) {
		        	count = 0;
					while (!start) {
						count++;
		        		line = readLine(istream);
		            	if (line.equalsIgnoreCase("--boundarydonotcross")) {
		            		start = true;
		            	}
		            }
		        	
		        	// Read content type line
		        	line = readLine(istream);
		        	//System.out.println(line);
		        	
		        	// Read data size line
		        	line = readLine(istream);
		        	//System.out.println(line);
		            length = Integer.parseInt(line.split(" ")[1]);
		            //System.out.println("Image size: " + length);
		            
		            while((line = readLine(istream)) != "");
		            // X-timestamp line
		            //line = readLine(istream);
		            //System.out.println(line);
		            // Read empty line
		            
		            //System.out.println(line);
		            
		            // Read image bytes
		            // No all bytes are necessarily ready when the stream is
		            // being read and the while loop ensures that all bytes
		            // will be read
		            bytesRead = 0;
		            byteArray = new byte[length];
		            while (bytesRead < length) {
		            	if (istream.available() > 0) {
		            		byteArray[bytesRead++] = (byte) istream.read();
		            	}
		            }
		            
		            // Read empty line
		            //line = readLine(istream);
		            
		            in = new ByteArrayInputStream(byteArray);
		        	image = ImageIO.read(in);
		        	setChanged();
		        	notifyObservers(image);
		        	
		        	start = false;
		        }
		    } catch (Exception e) {
		    	if (connected && firstError) {
		    		String error = "Connection to webcam lost. Using url" 
						+ "=" + requestUrl + ". Retrying " 
						+ "connection every " + RECONNECT_DELAY/1000 + "s";
		    		setChanged();
					notifyObservers(error);
					statusNotifier.setChanged();
					statusNotifier.notifyObservers(errText);
		    		connected = false;
		    		firstError = false;
		    	} else if (firstError) {
		    		String error = "No connection to webcam. Using url" 
						+ "=" + requestUrl + ". Retrying " 
						+ "connection every " + RECONNECT_DELAY/1000 + "s";
					setChanged();
					notifyObservers(error);
					statusNotifier.setChanged();
					statusNotifier.notifyObservers(errText);
		    		firstError = false;
		    	}
		    	
		    	start = false;
		    	
		    	try {
					istream.close();
				} catch (Exception e1) {}
				
				try {
					Thread.sleep(RECONNECT_DELAY);
				} catch (InterruptedException e2) {}
		    }
               } 
	}
}
